package org.hhf.core;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * SortedSetRedis类实现了Redis的有序集合数据类型操作
 */
public class SortedSetRedis {
    private final RedisCore core;
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public SortedSetRedis(RedisCore core) {
        this.core = core;
    }

    /**
     * 有序集合的内部实现类
     */
    public static class ZSet {
        // 存储成员到分数的映射
        private final ConcurrentHashMap<String, Double> memberScores = new ConcurrentHashMap<>();
        // 存储分数到成员列表的映射，用于范围查询
        private final TreeMap<Double, Set<String>> scoreMembers = new TreeMap<>();

        public ConcurrentHashMap<String, Double> getMemberScores() {
            return memberScores;
        }

        public TreeMap<Double, Set<String>> getScoreMembers() {
            return scoreMembers;
        }
    }

    /**
     * 获取有序集合，如果不存在则创建
     */
    @SuppressWarnings("unchecked")
    private ZSet getOrCreateZSet(String key) {
        Object value = core.get(key);
        if (value == null || !(value instanceof ZSet)) {
            ZSet zset = new ZSet();
            core.put(key, zset, RedisCore.DataType.ZSET);
            return zset;
        }
        return (ZSet) value;
    }

    /**
     * 向有序集合中添加元素
     */
    public Long zadd(String key, double score, String member) {
        lock.writeLock().lock();
        try {
            ZSet zset = getOrCreateZSet(key);
            ConcurrentHashMap<String, Double> memberScores = zset.getMemberScores();
            TreeMap<Double, Set<String>> scoreMembers = zset.getScoreMembers();
            
            // 如果成员已存在，先移除旧的分数关联
            if (memberScores.containsKey(member)) {
                Double oldScore = memberScores.get(member);
                if (oldScore.equals(score)) {
                    return 0L; // 分数相同，没有变化
                }
                removeFromScoreMembers(scoreMembers, oldScore, member);
            }
            
            // 添加新的分数和成员
            memberScores.put(member, score);
            addToScoreMembers(scoreMembers, score, member);
            
            return 1L;
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 从有序集合中移除元素
     */
    public Long zrem(String key, String... members) {
        lock.writeLock().lock();
        try {
            ZSet zset = getOrCreateZSet(key);
            ConcurrentHashMap<String, Double> memberScores = zset.getMemberScores();
            TreeMap<Double, Set<String>> scoreMembers = zset.getScoreMembers();
            
            long removed = 0;
            for (String member : members) {
                Double score = memberScores.remove(member);
                if (score != null) {
                    removeFromScoreMembers(scoreMembers, score, member);
                    removed++;
                }
            }
            
            return removed;
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 获取有序集合的指定范围元素（按分数从小到大）
     */
    public List<String> zrange(String key, long start, long end) {
        lock.readLock().lock();
        try {
            ZSet zset = getOrCreateZSet(key);
            ConcurrentHashMap<String, Double> memberScores = zset.getMemberScores();
            
            // 转换为按分数排序的列表
            List<Map.Entry<String, Double>> sortedEntries = new ArrayList<>(memberScores.entrySet());
            sortedEntries.sort(Map.Entry.comparingByValue());
            
            // 处理索引
            int size = sortedEntries.size();
            if (start < 0) {
                start = Math.max(0, size + start);
            }
            if (end < 0) {
                end = size + end;
            }
            
            if (start >= size || end < 0 || start > end) {
                return Collections.emptyList();
            }
            
            end = Math.min(end, size - 1);
            
            List<String> result = new ArrayList<>((int) (end - start + 1));
            for (long i = start; i <= end; i++) {
                result.add(sortedEntries.get((int) i).getKey());
            }
            
            return result;
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取元素的排名（从0开始，分数从小到大）
     */
    public Long zrank(String key, String member) {
        lock.readLock().lock();
        try {
            ZSet zset = getOrCreateZSet(key);
            ConcurrentHashMap<String, Double> memberScores = zset.getMemberScores();
            
            if (!memberScores.containsKey(member)) {
                return null;
            }
            
            // 转换为按分数排序的列表
            List<Map.Entry<String, Double>> sortedEntries = new ArrayList<>(memberScores.entrySet());
            sortedEntries.sort(Map.Entry.comparingByValue());
            
            // 查找排名
            for (int i = 0; i < sortedEntries.size(); i++) {
                if (sortedEntries.get(i).getKey().equals(member)) {
                    return (long) i;
                }
            }
            
            return null;
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取元素的逆序排名（从0开始，分数从大到小）
     */
    public Long zrevrank(String key, String member) {
        lock.readLock().lock();
        try {
            ZSet zset = getOrCreateZSet(key);
            ConcurrentHashMap<String, Double> memberScores = zset.getMemberScores();
            
            if (!memberScores.containsKey(member)) {
                return null;
            }
            
            // 转换为按分数排序的列表
            List<Map.Entry<String, Double>> sortedEntries = new ArrayList<>(memberScores.entrySet());
            sortedEntries.sort(Map.Entry.<String, Double>comparingByValue().reversed());
            
            // 查找排名
            for (int i = 0; i < sortedEntries.size(); i++) {
                if (sortedEntries.get(i).getKey().equals(member)) {
                    return (long) i;
                }
            }
            
            return null;
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 增加元素的分数
     */
    public Double zincrby(String key, double increment, String member) {
        lock.writeLock().lock();
        try {
            ZSet zset = getOrCreateZSet(key);
            ConcurrentHashMap<String, Double> memberScores = zset.getMemberScores();
            TreeMap<Double, Set<String>> scoreMembers = zset.getScoreMembers();
            
            // 获取当前分数，如果不存在则为0
            Double currentScore = memberScores.getOrDefault(member, 0.0);
            double newScore = currentScore + increment;
            
            // 如果成员已存在，先移除旧的分数关联
            if (memberScores.containsKey(member)) {
                removeFromScoreMembers(scoreMembers, currentScore, member);
            }
            
            // 更新分数
            memberScores.put(member, newScore);
            addToScoreMembers(scoreMembers, newScore, member);
            
            return newScore;
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 获取有序集合的大小
     */
    public Long zcard(String key) {
        lock.readLock().lock();
        try {
            ZSet zset = getOrCreateZSet(key);
            return (long) zset.getMemberScores().size();
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 获取元素的分数
     */
    public Double zscore(String key, String member) {
        lock.readLock().lock();
        try {
            ZSet zset = getOrCreateZSet(key);
            return zset.getMemberScores().get(member);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 辅助方法：将成员添加到分数-成员映射中
     */
    private void addToScoreMembers(TreeMap<Double, Set<String>> scoreMembers, double score, String member) {
        scoreMembers.computeIfAbsent(score, k -> ConcurrentHashMap.newKeySet()).add(member);
    }

    /**
     * 辅助方法：从分数-成员映射中移除成员
     */
    private void removeFromScoreMembers(TreeMap<Double, Set<String>> scoreMembers, double score, String member) {
        Set<String> members = scoreMembers.get(score);
        if (members != null) {
            members.remove(member);
            if (members.isEmpty()) {
                scoreMembers.remove(score);
            }
        }
    }
}